/*
 * Test.cpp
 *
 */

#include <iostream>
#include <iterator>
#include <vector>
#include <iterator>
#include <algorithm>
#include <cstdlib>
#include <iomanip>
using namespace std;

//template <class T> func(T x) {};
//template <class T> func<T*>(T* x) {};

//template <class T>
//class myObj { template <class R> memFunc() {} };
//template <class T>
//class myObj<T*> {};

//template <int x> int func() {return x;}
//template <double x> double func() {return x;}

//template <class X> void func(X val) { cout << "template <class X> void func(X val)" << endl; }
//template <> void func<double>(double val) { cout << "template <> void func<double>(double val)" << endl; }
//
//class obj
//{
//    public:
//        void callFunc() { func(4.5); }
//    private:
//        void func(int val) { cout << "void func(int val)" << endl; }
//};
//
//int main() { obj *po = new obj; po->callFunc(); delete po; }

//class Sample {
//public:
//        int *ptr;
//        Sample(int i)
//        {
//        	cout << "Sample::c-tor: " << i << endl;
//	        ptr = new int(i);
//        }
//
//        ~Sample()
//        {
//        	cout << "Sample::d-tor: " << *ptr << endl;
//	        delete ptr;
//        }
//        void PrintVal()
//        {
//	        cout << "The value is " << *ptr << endl;
//        }
//};
//
//void SomeFunc(Sample x)
//{
//	cout << "Say i am in someFunc " << endl;
//}
//
//int main()
//{
//	Sample s1 = 10;
//	SomeFunc(s1);
//	s1.PrintVal();
//}

//struct base {
//	int a,b;
//	base();
//	virtual int function1();
//};
//
//struct derv1 : base {
//	int b,c,d;
//	derv1();
//	virtual int function1();
//};
//
//struct derv2 : base {
//	int a,e;
//};
//
//base::base() {
//	a=2; b=3;
//}
//derv1::derv1() {
//	b=5; c=10; d=11;
//}
//int base::function1() {
//	return(100);
//}
//int derv1::function1() {
//	return(200);
//}
//
//int main() {
//	base ba;
//	derv1 d1,d2;
//	cout << d1.a << " " << d1.b << endl;
//}

typedef vector<int> VectorInt;
typedef vector<double> VectorDbl;
typedef bool (* UnPredInt)(const int&);
typedef bool (* BinPredInt)(const int&, const int&);

template<int threshold>
inline bool unPredIntGt( const int &val ) {
	cout << "Called unPredIntGt<" << threshold << ">( " << val << " )" << endl;
	return val > threshold;
}

bool unPredIntGt5( const int &i ) {
	cout << "Called unPredIntGt5( " << i << " )" << endl;
	return i > 5 ? true : false;
}

template<typename T>
inline bool binPredEq( const T &a, const T &b ) {
	cout << "Called binPredEq( " << a << ", " << b << " )" << endl;
	return a == b;
}

template<typename T>
struct BinPredGt : binary_function<T, T, bool> {
	bool operator() ( const T &a, const T &b ) const {
		cout << "Called BinPredGt( " << a << ", " << b << " )" << endl;
		return a > b;
	}
};

template<typename T>
struct BinPredLt : binary_function<T, T, bool> {
	bool operator() ( const T &a, const T &b ) const {
		cout << "Called BinPredLt( " << a << ", " << b << " )" << endl;
		return a < b;
	}
};

bool binPredIntEq( const int &i, const int &j ) {
	cout << "Called binPredIntEq( " << i << ", " << j << " )" << endl;
	return i == j;
}

template<typename T>
inline void printElements( const T &collection, const char *title="" ) {
//	typename T::const_iterator pos;
	typedef typename T::value_type E;
	std::cout << title;
//	for( pos = collection.begin(); pos != collection.end(); ++pos )
//		std::cout << *pos << ' ';
	std::copy( collection.begin(), collection.end(),
			std::ostream_iterator<E>( std::cout, " " ) );
	std::cout << std::endl;
}

/* ---------------------------------- */
//int main() {
//	srand( time( NULL ) );
	VectorInt vecInt;
//	VectorDbl vecDbl;
//	for( int i = 0; i < 10; i++ ) {
//		vecInt.push_back( i + 1 );
//		double rd = (double)rand()/(double)RAND_MAX;
//		vecDbl.push_back( rd );
//	}
//	printElements( vecInt, "Source vector<int>: " );
//	VectorInt::iterator result = adjacent_find( vecInt.begin(), vecInt.end() );
//	VectorInt::iterator result = adjacent_find( vecInt.begin(), vecInt.end(), binPredEq<int> );
//	cout << "adjacent_find: ";
//	if( result != vecInt.end() )
//		cout << *result << endl;
//	else
//		cout << "none" << endl;
//	size_t counter = count_if( vecInt.begin(), vecInt.end(), unPredIntGt5 );
//	size_t counter = count_if( vecInt.begin(), vecInt.end(), unPredIntGt<5> );
//	size_t counter = count_if( vecInt.begin(), vecInt.end(), bind2nd( greater<int>(), 5) );
//	size_t counter = count_if( vecInt.begin(), vecInt.end(), bind2nd( BinPredGt<int>(), 5) );
//	cout << "count_if: " << counter << endl;
//	VectorInt::iterator loc = vecInt.begin() + 3;
//	insert_iterator< vector<int> > iit( vecInt, loc );
//	*iit++ = 100;
//	*iit++ = 200;
//	printElements( vecInt, "After insert_iterator: " );
//	cout << "Source vector<double>: ";
//	printVector( vecDbl );
//	make_heap( vecDbl.begin(), vecDbl.end() );
//	cout << "After make_heap: ";
//	for( VectorDbl::iterator it = vecDbl.begin(); it != vecDbl.end(); ++it )
//		cout << *it << " ";
//	cout << endl;
//	sort_heap( vecDbl.begin(), vecDbl.end() );
//	cout << "After sort_heap: ";
//	for( VectorDbl::iterator it = vecDbl.begin(); it != vecDbl.end(); ++it )
//		cout << *it << " ";
//	cout << endl;
//	sort( vecDbl.begin(), vecDbl.end(), greater<double>() );
//	cout << "After sort: ";
//	printVector( vecDbl );
//	bool done = next_permutation( vecDbl.begin(), vecDbl.end() );
//	cout << "After next_permutation [" << boolalpha << done << "]: ";
//	printVector( vecDbl );
//	cout << "Tests are empty" << endl;
//	cout << "Enter elements (press Enter + Ctrl-Z at the end): ";
//	VectorInt test( (istream_iterator<int>(cin)), (istream_iterator<int>()) );
//	printElements( test, "Entered: " );
//}
